package com.tt.job.container;

import sun.net.www.ParseUtil;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.AccessController;
import java.security.CodeSource;
import java.security.PermissionCollection;
import java.security.PrivilegedAction;

/**
 * 参考AppClassLoader实现的类加载器
 **/
public class ContainerClassLoader extends URLClassLoader {

    public ContainerClassLoader(URL[] urls, ClassLoader parent) {
        super(urls, parent);
    }


    public static ClassLoader getClassLoader(final ClassLoader parent, final String classPath) throws IOException {
        final File[] var2 = classPath == null ? new File[0] : getClassPath(classPath);
        return AccessController.doPrivileged((PrivilegedAction<ContainerClassLoader>) () -> {
            URL[] urls = classPath == null ? new URL[0] : pathToURLs(var2);
            return new ContainerClassLoader(urls, parent);
        });
    }

    private static File[] getClassPath(String classPath) {
        File[] classFiles;
        if (classPath != null) {
            int index = 0;
            int length = 1;

            int var5;
            int var7;
            for (var5 = 0; (var7 = classPath.indexOf(File.pathSeparator, var5)) != -1; var5 = var7 + 1) {
                ++length;
            }

            classFiles = new File[length];

            for (var5 = 0; (var7 = classPath.indexOf(File.pathSeparator, var5)) != -1; var5 = var7 + 1) {
                if (var7 - var5 > 0) {
                    classFiles[index++] = new File(classPath.substring(var5, var7));
                } else {
                    classFiles[index++] = new File(".");
                }
            }

            if (var5 < classPath.length()) {
                classFiles[index++] = new File(classPath.substring(var5));
            } else {
                classFiles[index++] = new File(".");
            }

            if (index != length) {
                File[] var6 = new File[index];
                System.arraycopy(classFiles, 0, var6, 0, index);
                classFiles = var6;
            }
        } else {
            classFiles = new File[0];
        }

        return classFiles;
    }

    private static URL[] pathToURLs(File[] files) {
        URL[] urls = new URL[files.length];

        for (int i = 0; i < files.length; ++i) {
            urls[i] = getFileURL(files[i]);
        }

        return urls;
    }

    static URL getFileURL(File file) {
        try {
            file = file.getCanonicalFile();
        } catch (IOException var3) {
        }

        try {
            return ParseUtil.fileToEncodedURL(file);
        } catch (MalformedURLException var2) {
            throw new InternalError(var2);
        }
    }

    /**
     * Override loadClass so we can checkPackageAccess.
     */
    @Override
    public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        int index = name.lastIndexOf('.');
        if (index != -1) {
            SecurityManager securityManager = System.getSecurityManager();
            if (securityManager != null) {
                securityManager.checkPackageAccess(name.substring(0, index));
            }
        }

        return super.loadClass(name, resolve);
    }

    /**
     * allow any classes loaded from classpath to exit the VM.
     */
    @Override
    protected PermissionCollection getPermissions(CodeSource codesource) {
        PermissionCollection perms = super.getPermissions(codesource);
        perms.add(new RuntimePermission("exitVM"));
        return perms;
    }
}
